package Test1.Thermometry;

import Test1.HCNetSDK;
import Test1.PlayCtrl;
import com.sun.jna.Native;
import com.sun.jna.NativeLong;
import com.sun.jna.Pointer;
import com.sun.jna.examples.win32.W32API;
import com.sun.jna.ptr.ByteByReference;
import com.sun.jna.ptr.NativeLongByReference;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Scanner;

/**
 * Created by panting6 on 2021/2/21.
 */
public class P2PRealData {
    static HCNetSDK hCNetSDK = HCNetSDK.INSTANCE;
    static PlayCtrl playControl = PlayCtrl.INSTANCE;
    FileOutputStream realdata;
    fRealDataCallBack_V30 fRealDataCallBack_V30;//预览回调函数实现
    SimpleDateFormat sf = new SimpleDateFormat("yyyyMMddHHmmss");
    String newName = sf.format(new Date());
    NativeLongByReference m_lPort;//回调预览时播放库端口指针
    int lRealPlayHandle;

    /**
     * 获取数据，控制台输入控制是否结束测温并写入数据
     *
     * @param lUserID 用户登录句柄
     * @throws InterruptedException
     */
    public void getData(int lUserID,int iChannelNum) throws InterruptedException {

        p2PRealData(lUserID, iChannelNum);

        System.out.print("是否测温结束(Y/N)：");
        Scanner input = new Scanner(System.in);
        //循环从键盘输入命令，当输入Y表示测温结束
        while (true) {
            String str = input.next();
            if (str.equals("Y")) {
                outOfRealPlay();
                return;
            }
        }
    }

    /**
     * 全屏测温
     *
     * @param lUserID     用户登录句柄
     * @param iChannelNum 通道号
     * @throws InterruptedException
     */
    public void p2PRealData(int lUserID, int iChannelNum) throws InterruptedException {
        HCNetSDK.NET_DVR_XML_CONFIG_INPUT inputParam = new HCNetSDK.NET_DVR_XML_CONFIG_INPUT();
        inputParam.dwSize = inputParam.size();

        HCNetSDK.BYTE_ARRAY requestUrl = new HCNetSDK.BYTE_ARRAY(256);
        String urlString = "PUT /ISAPI/Thermal/channels/2/streamParam";
        System.arraycopy(urlString.getBytes(), 0, requestUrl.byValue, 0, urlString.length());
        requestUrl.write();
        inputParam.lpRequestUrl = requestUrl.getPointer();
        inputParam.dwRequestUrlLen = requestUrl.byValue.length;
        inputParam.dwRecvTimeOut = 5000;
        HCNetSDK.BYTE_ARRAY requestXml = new HCNetSDK.BYTE_ARRAY(16 * 1024);
        String xmlString =
                "<ThermalStreamParam version=\"2.0\"\n" +
                        "xmlns=\"http://www.hikvision.com/ver20/XMLSchema\">\n" +
                        "<videoCodingType>pixel-to-pixel_thermometry_data</videoCodingType>\n" +
                        "</ThermalStreamParam>";
        System.arraycopy(xmlString.getBytes(), 0, requestXml.byValue, 0, xmlString.length());
        requestXml.write();
        inputParam.lpInBuffer = requestXml.getPointer();
        inputParam.dwInBufferSize = requestXml.byValue.length;
        inputParam.write();

        HCNetSDK.BYTE_ARRAY outputXml = new HCNetSDK.BYTE_ARRAY(16 * 1024);
        outputXml.read();
        HCNetSDK.NET_DVR_XML_CONFIG_OUTPUT outputParam = new HCNetSDK.NET_DVR_XML_CONFIG_OUTPUT();
        outputParam.dwSize = outputParam.size();
        outputParam.lpOutBuffer = outputXml.getPointer();
        outputParam.dwOutBufferSize = outputXml.byValue.length;

        HCNetSDK.BYTE_ARRAY setStatusBuff = new HCNetSDK.BYTE_ARRAY(16 * 1024);
        setStatusBuff.read();
        outputParam.lpStatusBuffer = setStatusBuff.getPointer();
        outputParam.dwStatusSize = setStatusBuff.byValue.length;
        outputParam.write();

        if (hCNetSDK.NET_DVR_STDXMLConfig(lUserID, inputParam, outputParam)) {
            System.out.println("透传成功");
        } else {
            System.out.println("透传失败！！！ 错误码：" + hCNetSDK.NET_DVR_GetLastError());
        }

        HCNetSDK.NET_DVR_PREVIEWINFO lpPreviewInfo = new HCNetSDK.NET_DVR_PREVIEWINFO();
        lpPreviewInfo.lChannel = iChannelNum;
        lpPreviewInfo.hPlayWnd = null; //为NULL表示不解码显示
        lpPreviewInfo.byVideoCodingType = 1;  //1-热成像探测器产生的原始数据
        lpPreviewInfo.write();
        fRealDataCallBack_V30 = new fRealDataCallBack_V30();
        lRealPlayHandle = hCNetSDK.NET_DVR_RealPlay_V40(lUserID, lpPreviewInfo, fRealDataCallBack_V30, null);
        Thread.sleep(2000);
        System.out.print(lRealPlayHandle);
        if (lRealPlayHandle != -1) {
            //Todo 实时预览成功
        }
    }

    public void outOfRealPlay() {
        if (lRealPlayHandle != -1) {
            if (!hCNetSDK.NET_DVR_StopRealPlay(lRealPlayHandle)) {
                System.out.print("停止取流失败！！！  错误码：" + hCNetSDK.NET_DVR_GetLastError());
            }
            dataAnalysis test = new dataAnalysis();
            try {
                test.getFullScreenTemperatureData(".\\pic\\realData" + newName + ".data", widthSize, heightSize);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    // 输出测温数据宽度
    static int widthSize;
    // 输出测温数据高度
    static int heightSize;
    HCNetSDK.STREAM_FARME_INFO_TEMP struFarmeInfo = new HCNetSDK.STREAM_FARME_INFO_TEMP();

    /******************************************************************************
     * 内部类:   FRealDataCallBack
     * 实现预览回调数据
     ******************************************************************************/
    class fRealDataCallBack_V30 implements HCNetSDK.FRealDataCallback_V30 {

        //回调参数
        FileOutputStream bo;
        int countFrame = 0;
        int deleteFirst4ByteLogo = 0;

        //预览回调
        public void invoke(int lRealHandle, int dwDataType, ByteByReference pBuffer, int dwBufSize, Pointer pUser) {

            Pointer buff = pBuffer.getPointer();
            switch (dwDataType) {
                case HCNetSDK.NET_DVR_SYSHEAD: //系统头
                    if (!playControl.PlayM4_GetPort(m_lPort)) //获取播放库未使用的通道号
                    {
                        break;
                    }
                    if (dwBufSize > 0) {
                        if (!playControl.PlayM4_SetStreamOpenMode(m_lPort.getValue(), PlayCtrl.STREAME_REALTIME))  //设置实时流播放模式
                        {
                            break;
                        }

                        if (!playControl.PlayM4_OpenStream(m_lPort.getValue(), pBuffer, dwBufSize, 1024 * 1024)) //打开流接口
                        {
                            break;
                        }

                        if (!playControl.PlayM4_Play(m_lPort.getValue(), null)) //播放开始
                        {
                            break;
                        }
                    }
                case HCNetSDK.NET_DVR_STREAMDATA:   //码流数据

                    System.out.println("回调数据大小：" + dwBufSize);
                    System.out.println("回调帧数：" + countFrame);

                    if (dwBufSize == 132) {
                        deleteFirst4ByteLogo = 1;
                        countFrame++;

                        // 数据帧头信息转成结构体
                        struFarmeInfo.write();
                        Pointer pFarmeInfo = struFarmeInfo.getPointer();
                        pFarmeInfo.write(0, buff.getByteArray(0, struFarmeInfo.size()), 0, struFarmeInfo.size());
                        struFarmeInfo.read();
                        // 分辨率宽度
                        widthSize = struFarmeInfo.stRTDataInfo.u32Width;
                        heightSize = struFarmeInfo.stRTDataInfo.u32Height;
                    } else {

                        File file = new File(".\\pic\\realData" + newName + ".data");
                        if (!file.exists()) {
                            try {
                                file.createNewFile();
                            } catch (Exception e) {
                                e.printStackTrace();
                            }
                        }

                        try {
                            bo = new FileOutputStream(file, true);
                        } catch (IOException e) {
                            e.printStackTrace();
                        }

                        try {
                            ByteBuffer buffer1 = buff.getByteBuffer(0, dwBufSize);
                            byte[] byte1 = new byte[dwBufSize];
                            buffer1.rewind();
                            buffer1.get(byte1);

                            //将每帧数据的前4个无用数据剔除，剩余的数据全部写入
                            for (int i = 0; i < byte1.length; i++) {
                                if (i % 76804 >= 4) {
                                    bo.write(byte1[i]);
                                }
                            }
                        } catch (FileNotFoundException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        } catch (IOException e) {
                            e.printStackTrace();
                        } finally {
                            try {
                                if (bo != null) {
                                    bo.close();
                                }
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                        }
                    }
            }
        }
    }
 }

